最近在看Difix3D(近期NVIDIA一个去除3DGS/NERF噪声的工作,是基于sd微调的),正好借此契机学习下SD的概念和原理。
将影像组织成向量,首先通过VAE的编码器预测一个高斯分布的均值和方差,将影像向量压缩为维度更低的、包含高斯噪声的潜空间变量z。U-Net网络在文本等condition的指导下,紧接着从潜变量z中预测其中的噪声ε。然后通过多步采样去噪得到纯净的变量z_0。VAE的解码器再将其恢复到原始影像的维度大小,得到生成影像。
text –(tokenizer)–> tokens –(text_encoder)–> vectors
text先经过tokenizer, 转为token
token: 文本拆分成字符,然后通过查询词表,将字符映射为整数id
然后经过text_encoder (CLIP), 转为语义向量
tokens → 词嵌入+位置编码 → 多层Transformer Encoder → 每个词的embedding
输出的文本向量,会输入U-net引导去噪过程。
images_vec –(vae-encoder)–> latent_vec z –(u-net)–> noise_vec –(vae-decoder)-> images_vec
为什么预测分布:应该是让模型学习到分布,而不是某一些特定的输入数据,否则不具有生成能力。
u-net: 从加噪声后的变量z中估计出噪声。这个过程通过交叉注意力机制将文本条件相结合。在u-net预测出噪声之后,还需要通过多步的还原得到干净的潜变量。重复去噪过程,直到时间步为0.
1 | z = VAE_encoder(x) |
VAE-decoder: 将潜向量还原成原图大小的影像。
Difix的训练过程使用sd-turbo的预训练模型初始化。冻结:tokenizer、text-encoder、VAE-encoder。激活:u-net(去噪)、VAE-decoder、以及从encoder到decoder的skip-connection.